<?php

namespace App\Admin\Services;

use App\Models\AdminUser;
use Cache;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;

class GrantService
{
    /**
     * @description 生成角色
     * @param $name
     * @return \Illuminate\Database\Eloquent\Model|Role
     */
    public function createRoles($name)
    {
        return Role::query()->create(['name' => $name]);
    }

    /**
     * 更新用戶角色名稱
     * @param $name
     * @param $roleId
     * @return mixed
     */
    public function updateRoles($name, $roleId)
    {
        return Role::query()
            ->where('id', $roleId)
            ->update(['name' => $name]);
    }

    /**
     * 刪除角色
     * @param $roleId
     * @return mixed
     */
    public function deleteRoles($roleId)
    {
        if (!is_array($roleId)) {
            $roleId[] = $roleId;
        }
        return Role::query()
            ->whereIn('id', $roleId)
            ->delete();
    }

    /**
     * @description 生成權限
     * @param $name
     * @return \Illuminate\Database\Eloquent\Model|Permission
     */
    public function createPermission($name, $permission)
    {
        return Permission::query()
            ->create(['name' => $name, 'route' => $permission]);
    }

    /**
     * 更新用戶路由
     * @param $id
     * @param $name
     * @param $permission
     * @return int
     */
    public function syncPermission($id, $name, $permission)
    {
        return Permission::query()
            ->where('id', $id)
            ->update(['name' => $name, 'route' => $permission]);
    }

    /**
     * 刪除權限
     * @param $id
     * @return mixed
     */
    public function deletePermissions($id)
    {
        return Permission::query()
            ->whereIn('id', $id)
            ->delete();
    }

    /**
     * 獲取角色
     * @param array  $id
     * @param string $limit
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Eloquent\Model|null
     */
    public function getRoles($id = [], $limit = '')
    {
        if (is_array($id) && !empty($id)) {
            return Role::query()
                ->whereIn('id', $id)->get();
        }

        if ($id) {
            return Role::query()->find($id);
        }

        if ($limit) {
            return Role::query()->paginate($limit);
        }
        return Role::query()->get()->all();
    }

    /**
     * 獲取所有權限集合
     * @param string $limit
     * @return array|\Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public function getPermissions($limit = '')
    {
        if ($limit) {
            return Permission::query()->paginate($limit);
        }
        return Permission::query()->get()->all();
    }

    /**
     * 裝飾所有角色的權限
     * @param $roles
     * @return mixed
     */
    public function setPermissionsToRole($roles)
    {
        foreach ($roles as $role) {
            $ps = [];
            foreach ($role->permissions as $permission) {
                $ps[] = $permission->name;
            }
            $role->permission = implode(',', $ps);
        }
        return $roles;
    }

    /**
     * @description 獲取當個或多個權限
     * @param $id
     * @return mixed
     */
    public function getPermissionIn($id)
    {
        if (is_array($id)) {
            return Permission::query()->whereIn('id', $id)->get();
        }
        return Permission::query()->find($id);
    }

    /**
     * 獲取admin的所有權限路由數組
     * @param AdminUser $admin
     * @return array
     */
    public function getRoutes(AdminUser $admin)
    {
        return Cache::remember('admin:permissions:' . $admin->id, 1, function () use ($admin) {
            $routes      = [];
            $permissions = $admin->getAllPermissions();

            foreach ($permissions as $permission) {
                $routes = array_merge($routes, explode(',', $permission->route));
            }

            return array_unique($routes);
        });
    }

    /**
     * 判斷用戶是否對此路由有權限
     * @param           $route
     * @param AdminUser $admin
     * @return bool
     */
    public function hasPermissionTo($route, AdminUser $admin)
    {
        $routes = $this->getRoutes($admin);

        if (in_array('*', $routes) || in_array($route, $routes)) {
            return true;
        }

        return false;
    }

}
